基础后台框架

您所在的位置:网站首页 springboot 415 unsupported media type 基础后台框架

基础后台框架

#基础后台框架| 来源: 网络整理| 查看: 265

基础后台框架-基于SprongBoot+Maven

提示:框架基于SpringBoot+Maven构建 框架依赖:MySQL、Redis、Sa-Token、Redisson、MyBatis-Plus、HuTool 框架中,使用MyBatis-Plus已有的基础方法,可以快速实现基础业务

提示:使用此框架可以快速拓展自由业务逻辑

基础后台框架-基于SprongBoot+Maven+MySQL+Redis 基础后台框架-基于SprongBoot+Maven前言一、Maven下载依赖二、基础配置文件application.yml 1.源文件异常处理限流注解线程池配置熔断配置MyBatis-Plus配置Redis配置Redisson配置常量配置接口请求控制器基类控制器dao层服务层服务实现层实体自定义异常类自定义filter生成全局追踪ID统一返回封装类启动类 2.SQL文件

前言

框架依赖:MySQL、Redis、Sa-Token、Redisson、MyBatis-Plus 框架中,使用MyBatis-Plus已有的基础方法,可以快速实现基础业务。

一、Maven下载依赖

POM.XML是下载基础依赖的工具,可以根据实际需求,增加拓展

4.0.0 org.springframework.boot spring-boot-starter-parent 2.7.9 applet top.allopen.applet applet 0.0.1-SNAPSHOT Demo project for Spring Boot UTF-8 UTF-8 1.8 1.1.0 3.1.0 3.0.0 5.8.15 1.5.18 1.0.6 org.projectlombok lombok cn.hutool hutool-all ${hutool.version} com.alibaba druid ${druid.version} com.baomidou mybatis-plus-boot-starter ${mybatis-plus.version} org.springframework.boot spring-boot-starter-aop org.apache.commons commons-pool2 org.springframework.boot spring-boot-starter-web org.mybatis.spring.boot mybatis-spring-boot-starter ${mybatis.version} com.mysql mysql-connector-j runtime org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-data-redis redis.clients jedis org.redisson redisson 3.8.2 com.alibaba druid-spring-boot-starter 1.2.1 com.google.guava guava 30.1-jre com.yungouos.pay yungouos-pay-sdk 2.0.29 org.springframework.boot spring-boot-starter-validation cn.dev33 sa-token-spring-boot-starter 1.34.0 fr.opensagres.xdocreport org.apache.poi.xwpf.converter.pdf ${poi.version} com.netflix.hystrix hystrix-core ${hystrix.version} com.netflix.hystrix hystrix-javanica ${hystrix.version} applet src/main/resources **/*.properties **/*.xml **/*.yml true org.springframework.boot spring-boot-maven-plugin top.allopen.applet.AppletApplication repackage 二、基础配置文件 application.yml spring: profiles: active: dev mybatis-plus: mapper-locations: classpath:mapper/*.xml global-config: db-config: id-type: auto field-strategy: NOT_EMPTY db-type: MYSQL configuration: map-underscore-to-camel-case: true call-setters-on-nulls: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl logging: config: classpath:logback-spring.xml

application-dev.yml

server: port: 8088 ############## Sa-Token 配置 (文档: https://sa-token.cc) ############## sa-token: # token名称 (同时也是cookie名称) token-name: satoken # token有效期,单位s 默认30天, -1代表永不过期 timeout: 2592000 # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 activity-timeout: -1 # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) is-concurrent: true # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) is-share: true # token风格 token-style: uuid # 是否输出操作日志 is-log: false token-prefix: allopen.top spring: datasource: type: com.alibaba.druid.pool.DruidDataSource druid: # com.mysql.jdbc.Driver driverClassName: com.mysql.cj.jdbc.Driver # 换为自己的数据库信息 url: jdbc:mysql://ip:端口/数据库名称?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC username: 用户名 password: 密码 initial-size: 5 # 最大连接池个数 max-active: 20 # 最小连接池个数——》已经不再使用,配置了也没效果 min-idle: 5 # 配置获取连接等待超时的时间,单位毫秒,缺省启用公平锁,并发效率会有所下降 max-wait: 60000 # 打开PSCache,并且指定每个连接上PSCache的大小 pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 max-evictable-idle-time-millis: 60000 validation-query: SELECT 1 FROM DUAL # validation-query-timeout: 5000 # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 test-on-borrow: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 test-on-return: false # 建议配置为true,不影响性能,并且保证安全性。 # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 test-while-idle: true # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 connectionProperties: druid.stargeSql=true;druid.stat.slowSqlMillis=5000 # 通过别名的方式配置扩展插件,多个英文逗号分隔,常用的插件有: # 监控统计用的filter:stat #filters: #配置多个英文逗号分隔(统计,sql注入,log4j过滤) 防御sql注入的filter:wall filters: stat,wall stat-view-servlet: enabled: true url-pattern: /druid/* # login-username: root # login-password: root redis: # 换为自己的redis链接信息 host: ip port: 端口 password: 密码 database: 5 lettuce: pool: max-idle: 16 max-active: 20 min-idle: 8 mybatis: # config-location: classpath:mybatis.cfg2.xml # mybatis主配置文件所在路径 type-aliases-package: top.allopen.applet.entity # 定义所有操作类的别名所在包 mapper-locations: # 所有的mapper映射文件 - classpath:mapper/*.xml #showSql logging: level: com.example.demo.mapper: debug 1.源文件 异常处理 package top.allopen.applet.advice; import cn.hutool.json.JSONUtil; import com.google.common.collect.Lists; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import top.allopen.applet.res.Result; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import java.util.List; import java.util.stream.Collectors; /** * @Description: 全局异常处理 * @Package top.allopen.applet.advice * @Date 2023-03-11 * @Author Dale * @Since 3.1 */ @RestControllerAdvice public class ExceptionConfig { @ExceptionHandler(value = MethodArgumentNotValidException.class) public String handleValidException(MethodArgumentNotValidException e) { List list = e.getBindingResult().getAllErrors(); List data = Lists.newArrayList(); list.forEach(temp -> { data.add(temp.getDefaultMessage()); }); String result = JSONUtil.toJsonStr(Result.fail("参数校验发生异常", data)); return result; } @ExceptionHandler(value = ConstraintViolationException.class) public String handleConstraintViolationException(ConstraintViolationException e) { return e.getConstraintViolations() .stream() .map(ConstraintViolation::getMessage) .collect(Collectors.toList()).get(0); } } 限流注解 package top.allopen.applet.annotate; import java.lang.annotation.*; import java.util.concurrent.TimeUnit; /** * @Description: Description * @Package top.allopen.applet.annotate * @Date 2023-03-11 * @Author Dale * @Since 3.1 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Documented public @interface Limit { /** * 最多的访问限制次数 */ double permitsPerSecond () default 10D; /** * 获取令牌最大等待时间 */ long timeout() default 3000; /** * 获取令牌最大等待时间,单位(例:分钟/秒/毫秒) 默认:毫秒 */ TimeUnit timeunit() default TimeUnit.MILLISECONDS; /** * 得不到令牌的提示语 */ String msg() default "因流量限制,系统繁忙,请稍后再试."; }

自定义aop

package top.allopen.applet.aop; import cn.hutool.json.JSONUtil; import com.google.common.util.concurrent.RateLimiter; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import top.allopen.applet.annotate.Limit; import top.allopen.applet.res.Result; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * @Description: Description * @Package top.allopen.applet.aop * @Date 2023-03-11 * @Author Dale * @Since 3.1 */ @Slf4j @Aspect @Component public class LimitAop { /** * 不同的接口,不同的流量控制 * map的key为 Limiter.key */ private final Map limitMap = new HashMap(); @Around("@annotation(top.allopen.applet.annotate.Limit)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Limit limit = method.getAnnotation(Limit.class); if (limit != null) { String key = joinPoint.getTarget().getClass().getSimpleName() + method.getName(); RateLimiter rateLimiter = null; if (!limitMap.containsKey(key)) { rateLimiter = RateLimiter.create(limit.permitsPerSecond()); limitMap.put(key, rateLimiter); log.info("创建令牌桶: {}, 容量: {}", key, limit.permitsPerSecond()); } rateLimiter = limitMap.get(key); // 获取令牌 boolean acquire = rateLimiter.tryAcquire(limit.timeout(), limit.timeunit()); if (!acquire) { log.debug("令牌桶: {}, 获取令牌失败", key); this.responseFail(limit.msg()); return null; } } return joinPoint.proceed(); } /** * 直接向前端抛出异常 * @param msg 提示信息 */ private void responseFail(String msg) { HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); Result resultData = Result.fail(msg); response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); PrintWriter out = null; try { out = response.getWriter(); out.append(JSONUtil.toJsonStr(resultData)); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) { out.close(); } } } } 线程池配置 package top.allopen.applet.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import com.alibaba.druid.util.Utils; /** * @Description: Druid数据库连接池配置文件 * @Package top.allopen.applet.config * @Date 2023-03-11 * @Author Dale * @Since 3.1 */ @Configuration public class DruidConfig { private static final Logger logger = LoggerFactory.getLogger(DruidConfig.class); @Value("${spring.datasource.druid.url}") private String dbUrl; @Value("${spring.datasource.druid.username}") private String username; @Value("${spring.datasource.druid.password}") private String password; @Value("${spring.datasource.druid.driverClassName}") private String driverClassName; @Value("${spring.datasource.druid.initial-size}") private int initialSize; @Value("${spring.datasource.druid.max-active}") private int maxActive; @Value("${spring.datasource.druid.min-idle}") private int minIdle; @Value("${spring.datasource.druid.max-wait}") private int maxWait; @Value("${spring.datasource.druid.pool-prepared-statements}") private boolean poolPreparedStatements; @Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}") private int maxPoolPreparedStatementPerConnectionSize; @Value("${spring.datasource.druid.time-between-eviction-runs-millis}") private int timeBetweenEvictionRunsMillis; @Value("${spring.datasource.druid.min-evictable-idle-time-millis}") private int minEvictableIdleTimeMillis; @Value("${spring.datasource.druid.max-evictable-idle-time-millis}") private int maxEvictableIdleTimeMillis; @Value("${spring.datasource.druid.validation-query}") private String validationQuery; @Value("${spring.datasource.druid.test-while-idle}") private boolean testWhileIdle; @Value("${spring.datasource.druid.test-on-borrow}") private boolean testOnBorrow; @Value("${spring.datasource.druid.test-on-return}") private boolean testOnReturn; @Value("${spring.datasource.druid.filters}") private String filters; @Value("{spring.datasource.druid.connection-properties}") private String connectionProperties; /** * Druid 连接池配置 */ @Bean //声明其为Bean实例 public DruidDataSource dataSource() { DruidDataSource datasource = new DruidDataSource(); datasource.setUrl(dbUrl); datasource.setUsername(username); datasource.setPassword(password); datasource.setDriverClassName(driverClassName); datasource.setInitialSize(initialSize); datasource.setMinIdle(minIdle); datasource.setMaxActive(maxActive); datasource.setMaxWait(maxWait); datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); datasource.setMaxEvictableIdleTimeMillis(minEvictableIdleTimeMillis); datasource.setValidationQuery(validationQuery); datasource.setTestWhileIdle(testWhileIdle); datasource.setTestOnBorrow(testOnBorrow); datasource.setTestOnReturn(testOnReturn); datasource.setPoolPreparedStatements(poolPreparedStatements); datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); try { datasource.setFilters(filters); } catch (Exception e) { logger.error("druid configuration initialization filter", e); } datasource.setConnectionProperties(connectionProperties); return datasource; } /** * 去除监控页面底部的广告 */ @SuppressWarnings({ "rawtypes", "unchecked" }) @Bean @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true") public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) { // 获取web监控页面的参数 DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); // 提取common.js的配置路径 String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); final String filePath = "support/http/resources/js/common.js"; // 创建filter进行过滤 Filter filter = new Filter() { @Override public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); // 重置缓冲区,响应头不会被重置 response.resetBuffer(); // 获取common.js String text = Utils.readFromResource(filePath); // 正则替换banner, 除去底部的广告信息 text = text.replaceAll(" return new JdbcTemplate(dataSource) ; } /** * 配置 Druid 监控界面 */ @Bean public ServletRegistrationBean statViewServlet(){ ServletRegistrationBean srb = new ServletRegistrationBean(new StatViewServlet(),"/druid/*"); //设置控制台管理用户 // srb.addInitParameter("loginUsername","root"); // srb.addInitParameter("loginPassword","root"); //是否可以重置数据 srb.addInitParameter("resetEnable","false"); return srb; } @Bean public FilterRegistrationBean statFilter(){ //创建过滤器 FilterRegistrationBean frb = new FilterRegistrationBean(new WebStatFilter()); //设置过滤器过滤路径 frb.addUrlPatterns("/*"); //忽略过滤的形式 frb.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return frb; } } 熔断配置 package top.allopen.applet.config; import com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; /** * @Description: 开启 AOP 代理的支持 * @Package top.allopen.applet.config * @Date 2023-03-13 * @Author Dale * @Since 3.1 */ @Configuration @EnableAspectJAutoProxy public class HystrixConfig { @Bean public HystrixCommandAspect hystrixCommandAspect() { return new HystrixCommandAspect(); } } MyBatis-Plus配置 package top.allopen.applet.config; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor; import org.springframework.context.annotation.Bean; /** * @Description: Description * @Package top.allopen.applet.config * @Date 2023-03-10 * @Author Dale * @Since 3.1 */ public class MybatisPlusConfig { /** * mybatis-plus SQL执行效率插件【生产环境可以关闭】 */ @Bean public PerformanceInterceptor performanceInterceptor() { return new PerformanceInterceptor(); } /** * 分页插件 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } } Redis配置 package top.allopen.applet.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.time.Duration; /** * @Description: Description * @Package top.allopen.applet.config * @Date 2023-03-11 * @Author Dale * @Since 3.1 */ @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisSerializer redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //解决查询缓存转换异常的问题 ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); jackson2JsonRedisSerializer.setObjectMapper(om); // 配置序列化解决乱码 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(30)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager; } } Redisson配置 package top.allopen.applet.config; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Description: Description * @Package top.allopen.applet.config * @Date 2023-03-13 * @Author Dale * @Since 3.1 */ @Configuration public class RedissonConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.password}") private String paw; @Value("${spring.redis.port}") private String port; @Bean public RedissonClient getRedisson() throws Exception{ RedissonClient redisson = null; System.out.println(host); Config config = new Config(); config.useSingleServer() .setPassword(paw) .setAddress("http://"+host+":"+port); redisson = Redisson.create(config); System.out.println(redisson.getConfig().toJSON().toString()); return redisson; } } 常量配置 package top.allopen.applet.constant; /** * @Description: 常量配置 * @Package top.allopen.applet.constant * @Date 2023-03-11 * @Author Dale * @Since 3.1 */ public class Constant { /** * 全局请求追踪ID */ public static final String TRACE_ID = "traceId"; /** * 请求熔断时间 毫秒 */ public static final String FUSING_TIME = "5000"; /** * 常量 整数 0 */ public static final int FIX_INT_0 = 0; } 接口请求控制器 package top.allopen.applet.controller; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import top.allopen.applet.annotate.Limit; import top.allopen.applet.constant.Constant; import top.allopen.applet.entity.User; import top.allopen.applet.res.Result; import top.allopen.applet.service.UserService; import java.util.List; /** * @Description: Description * @Package top.allopen.applet.controller * @Date 2023-03-10 * @Author Dale * @Since 3.1 */ @SuppressWarnings("all") @RestController @RequestMapping("/test") public class TestController extends BaseController { @Autowired private StringRedisTemplate redisTemplate; @Autowired private UserService userService; @Limit @HystrixCommand(commandProperties= { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = Constant.FUSING_TIME), @HystrixProperty(name = "execution.timeout.enabled", value = "true") }, fallbackMethod="fallbackMethod") @RequestMapping(value = "list", method = RequestMethod.GET) public Result list() { redisTemplate.opsForValue().set("data", "data"); Object result = redisTemplate.opsForValue().get("data"); List data = userService.list(); return Result.success(data); } } 基类控制器 package top.allopen.applet.controller; import top.allopen.applet.res.Result; /** * @Description: Description * @Package top.allopen.applet.controller * @Date 2023-03-10 * @Author Dale * @Since 3.1 */ public class BaseController { /** * @apiNote 触发熔断机制返回数据 * * @author dale * @since 1.0 * @date 2023-03-13 9:36 * @return Result **/ protected Result fallbackMethod() { return Result.fail("触发熔断机制"); } } dao层 package top.allopen.applet.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import top.allopen.applet.entity.User; /** * @Description: Description * @Package top.allopen.applet.dao * @Date 2023-03-10 * @Author Dale * @Since 3.1 */ @Mapper public interface UserInfoDao extends BaseMapper { } 服务层 package top.allopen.applet.service; import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.stereotype.Service; import top.allopen.applet.entity.User; import java.util.List; /** * @Description: Description * @Package top.allopen.applet.service * @Date 2023-03-10 * @Author Dale * @Since 3.1 */ @Service public interface UserService extends IService { @Override List list(); } 服务实现层 package top.allopen.applet.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import top.allopen.applet.dao.UserInfoDao; import top.allopen.applet.entity.User; import top.allopen.applet.service.UserService; import java.util.List; import java.util.concurrent.TimeUnit; /** * @Description: Description * @Package top.allopen.applet.service.impl * @Date 2023-03-10 * @Author Dale * @Since 3.1 */ @Service public class UserInfoServiceImpl extends ServiceImpl implements UserService { @Autowired private RedissonClient redissonClient; @Override @Cacheable(value = "top.allopen.applet.service.impl.UserInfoServiceImpl.list") public List list() { List result = null; RLock lock = redissonClient.getLock("user:list-lock"); try { boolean isLock = lock.tryLock(5,30, TimeUnit.SECONDS); if(isLock) { result = super.list(); } } catch (Exception e) { } finally { if(lock.isHeldByCurrentThread()) { lock.unlock(); } } return result; } } 实体 package top.allopen.applet.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; /** * @Description: Description * @Package top.allopen.applet.entity * @Date 2023-03-10 * @Author Dale * @Since 3.1 */ @TableName("user_info") public class User implements Serializable { @TableId(type = IdType.AUTO) private Integer id; @TableField(value = "userName") private String userName; @TableField(value = "passWord") private String passWord; @TableField(value = "realName") private String realName; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } public String getRealName() { return realName; } public void setRealName(String realName) { this.realName = realName; } @Override public String toString() { return "User{" + "id=" + id + ", userName='" + userName + '\'' + ", passWord='" + passWord + '\'' + ", realName='" + realName + '\'' + '}'; } } 自定义异常类 package top.allopen.applet.exception; import lombok.Data; /** * @Description: 自定义异常 * @Package top.allopen.applet.exception * @Date 2023-03-13 * @Author Dale *@Since 3.1 */ @Data public class CustomException extends RuntimeException { private Integer code; private String msg; public CustomException() { super(); } public CustomException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } public CustomException(String message, Throwable cause) { super(message, cause); } public CustomException(String message) { super(message); } public CustomException(String message,Integer code) { super(message); this.code = code; } public CustomException(Throwable cause) { super(cause); } public CustomException(Throwable cause,Integer code) { super(cause); this.code = code; } public static CustomException requestFast() { CustomException e = new CustomException("请求过快", 429); return e; } } 自定义filter生成全局追踪ID package top.allopen.applet.filter; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import top.allopen.applet.constant.Constant; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.UUID; /** * @Description: Description * @Package top.allopen.applet.filter * @Date 2023-03-11 * @Author Dale * @Since 3.1 */ @Component @Slf4j public class TraceFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { MDC.put(Constant.TRACE_ID, getTraceId()); filterChain.doFilter(httpServletRequest, httpServletResponse); } private String getTraceId() { long timestamp = System.currentTimeMillis(); UUID uuid = UUID.randomUUID(); String uniqueId = timestamp + uuid.toString().replace("-", ""); return uniqueId; } } 统一返回封装类 package top.allopen.applet.res; import cn.hutool.json.JSONUtil; import lombok.Data; import org.slf4j.MDC; import top.allopen.applet.constant.Constant; //import top.allopen.applet.util.HitCache; import java.io.Serializable; import java.util.Optional; /** * @Description: Description * @Package top.allopen.applet.res * @Date 2023-03-10 * @Author Dale * @Since 3.1 */ @Data public class Result implements Serializable { /** * serialVersionUID */ private static final long serialVersionUID = 1L; private static final String SUCCESS_MSG = "success"; private static final int SUCCESS_CODE = 100; private static final int FAIL_CODE = 116; /** * 是否成功 * * @Description 是否成功 */ private boolean success = false; /** * 是否命中缓存 * * @Description 是否命中缓存 */ // private boolean hitcache = HitCache.getInstance().get(); /** * 错误信息 * * @Description 错误信息 */ private String message; /** * @Description */ private String sysMessage; /** * 错误信息 * * @Description 错误信息 */ private String errorMsg; /** * @Description */ private String version = "1.0"; /** * 主数据 * * @Description 主数据 */ private T responseData; /** * 返回码 * * @Description 返回码 */ private int msgCode; /** * 接口耗时 * * @Description 接口耗时 */ private long timing; /** * 追踪码 * @Description 追踪码 */ private String requestId = MDC.get(Constant.TRACE_ID); /** * 返回的额外数据 * * @Description 返回的额外数据 */ private Object ext; private Result(boolean success, String message, T responseData, int code) { this.success = success; this.message = message; this.responseData = responseData; this.msgCode = code; } public Result() { } public Optional optional() { return success ? Optional.of(responseData) : Optional.empty(); } public void setData(T data) { this.responseData = data; } public void setMessage(String message) { this.message = message; } public void setSuccess(boolean success) { this.success = success; } public static Result success() { return success(null, null); } public static Result success(T data) { return success(data, null); } public static Result success(T data, int code) { return success(data, null, code); } public static Result success(Optional data) { if (data != null && data.isPresent()) return success(data.get(), null); return success(); } public static Result success(Optional data, int code) { if (data != null && data.isPresent()) return success(data.get(), null, code); return success(); } public static Result success(T data, String desc) { return new Result(true, (desc == null || desc.trim().length() return fail(e.getMessage()); } public static Result fail(String errMsg) { Result result = new Result(); result.success = false; result.errorMsg = errMsg; result.msgCode = FAIL_CODE; return result; } public static Result fail(String errorMsg, int code) { Result result = new Result(); result.success = false; result.errorMsg = errorMsg; result.msgCode = code; return result; } public static Result fail(String errorMsg, T responseData) { Result result = new Result(); result.success = false; result.errorMsg = errorMsg; result.responseData = responseData; result.msgCode = FAIL_CODE; return result; } public static Result fail(String errorMsg, T responseData, int code) { Result result = new Result(); result.success = false; result.errorMsg = errorMsg; result.responseData = responseData; result.msgCode = code; return result; } public Result responseData(T responseData) { this.responseData = responseData; return this; } public Result message(String message) { this.message = message; return this; } public Result code(int code) { this.msgCode = code; return this; } public Result errorMsg(String errorMsg) { this.errorMsg = errorMsg; return this; } public Result requestId(String requestId) { // this.requestId = requestId; return this; } public Result ext(Object ext) { this.ext = ext; return this; } public String toJson() { return JSONUtil.toJsonStr(this); } public void setTiming(Long timing) { this.timing = timing; } public long getTiming() { return timing; } // public void setRequestId(String requestId) { // this.requestId = requestId; // } } 启动类 package top.allopen.applet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SuppressWarnings("all") @SpringBootApplication public class AppletApplication { public static void main(String[] args) { SpringApplication.run(AppletApplication.class, args); } } 2.SQL文件 CREATE TABLE `user` ( `id` int(32) NOT NULL AUTO_INCREMENT, `userName` varchar(32) NOT NULL, `passWord` varchar(50) NOT NULL, `realName` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3